package cn.thoughtworks.school.notifications;

import cn.thoughtworks.school.entities.Notification;
import cn.thoughtworks.school.notifications.impl.*;
import cn.thoughtworks.school.services.ProgramCenterService;
import cn.thoughtworks.school.services.UserCenterService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Component
@Slf4j
public class NotificationFactory {
  @Autowired
  private UserCenterService userCenterService;
  @Autowired
  protected ProgramCenterService programCenterService;
  private String CURRENT_NOTIFICATION_TYPE;
  protected Map data;
  private Map<String, String> properties;

  public NotificationFactory() {
  }

  public NotificationFactory(Map data, Properties properties, UserCenterService userCenterService, ProgramCenterService programCenterService) {
    this.CURRENT_NOTIFICATION_TYPE = data.get("type").toString();
    this.data = data;
    this.properties = properties.getNotifications();
    this.userCenterService = userCenterService;
    this.programCenterService = programCenterService;
  }

  public NotificationFactory factory(Map data, Properties props) {
    String type = data.get("type").toString();
    switch (type) {
      case "TUTOR_FOLLOW_STUDENT":
        return new TutorFollowStudentNotification(data, props, userCenterService, programCenterService);
      case "TUTOR_MODIFY_ASSIGNMENT_STATUS":
        return new TutorModifyAssignmentNotification(data, props, userCenterService, programCenterService);
      case "TUTOR_COMMENT_ASSIGNMENT":
        return new TutorCommentAssignmentNotification(data, props, userCenterService, programCenterService);
      case "STUDENT_MODIFY_ASSIGNMENT_STATUS":
        return new StudentModifyAssignmentNotification(data, props, userCenterService, programCenterService);
      case "STUDENT_COMMENT_ASSIGNMENT":
        return new StudentCommentAssignmentNotification(data, props, userCenterService, programCenterService);
      case "GROWTH_NOTE_STUDENT_TO_TUTOR":
        return new GrowthLogStudentToTutorNotification(data, props, userCenterService, programCenterService);
      case "GROWTH_NOTE_TUTOR_TO_STUDENT":
        return new GrowthLogTutorToStudentNotification(data, props, userCenterService, programCenterService);
      case "GROWTH_EXCELLENT_NOTE":
        return new GrowthExcellentLogNotification(data, props, userCenterService, programCenterService);
    }
    return null;
  }

  protected String getMessage() {
    return "";
  }

  protected String getMessage_en() {
    return "";
  }

  private String getUrl() {
    String url = properties.get(CURRENT_NOTIFICATION_TYPE);
    log.info("all url:" + properties);
    for (Object key : data.keySet()) {
      url = url.replace(":" + key, data.get(key).toString());
    }
    log.info("current url" + url);
    return url;
  }

  public List<Notification> getNotifications() {
    if ("".equals(data.get("receiverId"))) {
      return new ArrayList<>();
    }
    List<String> receiverIds = Arrays.asList(data.get("receiverId").toString().split(","));
    return receiverIds.stream().map(receiverId -> Notification.builder()
      .receiverId(Long.parseLong(receiverId))
      .senderId(Long.parseLong(data.get("senderId").toString()))
      .message(getMessage())
      .message_en(getMessage_en())
      .isRead(false)
      .type(CURRENT_NOTIFICATION_TYPE)
      .createTime(new SimpleDateFormat("yyyy-MM-dd").format(new Date()))
      .url(getUrl()).build()
    ).collect(Collectors.toList());

  }

  protected Map getProgram() {
    Long programId = Long.parseLong(data.get("programId").toString());
    return programCenterService.getProgramById(programId);
  }

  protected Map getUser(Long id) {
    return userCenterService.getUserInfo(id);
  }

  protected String getUserName(Map user) {
    if (Objects.nonNull(user.get("name"))) {
      return user.get("name").toString();
    }
    return user.get("userName").toString();
  }

  protected Map getAssignment(String assignmentId) {
    return programCenterService.getAssignment(assignmentId);
  }

  protected String getMyTutorIds() {
    List<Map> tutors = programCenterService.getMyTutors(Long.parseLong(data.get("programId").toString()), Long.parseLong(data.get("senderId").toString()));
    return String.join(",", tutors.stream().map(item -> item.get("tutorId").toString()).collect(Collectors.toList()));
  }
}
